#include "main.h"
#include <webp/encode.h>
#include <webp/decode.h>

int WebPCodec::encode(byte* imgData, byte* pktData)
{   
	int width = gConfig->totalWidth, height = gConfig->totalHeight;
    const int stride = width * 3;

	#ifdef WEBP_DIRECTLY
    byte tmp[stride];
    byte *end = imgData + stride * (height - 1);
    for (int i = 0; i < height / 2; i++) {
		memcpy(tmp, imgData + i * stride, stride);
		memcpy(imgData + i * stride, end - i * stride, stride);
		memcpy(end - i * stride, tmp, stride);
	}
    uint8_t *output;
    size_t size = WebPEncodeBGR(imgData, width, height, stride, 75, &output);
    #else
    uint8_t *output;
	size_t size = WebPEncodeRGB(imgData, width, height, stride, 75, &output);
	#endif

    if (size == 0) {
        LOG("Failed to encode rgb frame to webp\n");
        return 0;
    }

	#ifdef CODEC_LOG
		fprintf(f, "frame: %ld size:%d\n", pts++, size);
	#endif

    memcpy(pktData, output, size);
    free(output);

    return size;
}

int WebPCodec::decode(byte* pktData, int pktSize, byte* imgData)
{
    int width, height;

	#ifdef WEBP_DIRECTLY
    uint8_t * output = WebPDecodeBGR(pktData, pktSize, &width, &height);
    #else
	uint8_t * output = WebPDecodeRGB(pktData, pktSize, &width, &height);
    #endif
	if (output == NULL) {
        LOG("Failed to decode webp to rgb\n");
        return -1;
    }

	int pad_size = (4 - (width * 3) % 4) % 4;
	int wid_size = width * 3;
    int size = 54 + (wid_size + pad_size) * height;

    byte bmp_file_header[14] = { 'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, };
	byte bmp_info_header[40] = { 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, };
	byte bmp_pad[3] = { 0, 0, 0 };

	bmp_file_header[2] = (unsigned char)size;
	bmp_file_header[3] = (unsigned char)(size >> 8);
	bmp_file_header[4] = (unsigned char)(size >> 16);
	bmp_file_header[5] = (unsigned char)(size >> 24);

	bmp_info_header[4] = (unsigned char)(width);
	bmp_info_header[5] = (unsigned char)(width >> 8);
	bmp_info_header[6] = (unsigned char)(width >> 16);
	bmp_info_header[7] = (unsigned char)(width >> 24);
	bmp_info_header[8] = (unsigned char)(height);
	bmp_info_header[9] = (unsigned char)(height >> 8);
	bmp_info_header[10] = (unsigned char)(height >> 16);
	bmp_info_header[11] = (unsigned char)(height >> 24);

    memcpy(imgData, bmp_file_header, 14);
	memcpy(imgData + 14, bmp_info_header, 40);
	byte* pos = imgData + 54;
    byte* pixels = output;
    
	for (int i = 0; i < height; i++) {
		memcpy(pos, pixels, wid_size);
		pos += wid_size;
		pixels += wid_size;
		memcpy(pos, bmp_pad, pad_size);
		pos += pad_size;
	}

    free(output);
    return size;
}

